package com.wxapp.market.service.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import com.baomidou.mybatisplus.core.toolkit.support.SFunction;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wxapp.common.constant.base.IBaseService;
import com.wxapp.common.constant.pojo.vm.ResultVm;
import com.wxapp.common.constant.pojo.vo.UserVo;
import com.wxapp.common.util.check.CheckUtil;
import com.wxapp.common.util.condition.ConditionUtil;
import com.wxapp.common.util.copy.CopyUtil;
import com.wxapp.common.util.date.LocalDateTimeUtil;
import com.wxapp.market.api.feign.GoodsFeign;
import com.wxapp.market.api.pojo.entity.CouponDO;
import com.wxapp.market.api.pojo.entity.CouponGoodsDO;
import com.wxapp.market.api.pojo.entity.CouponUserDO;
import com.wxapp.market.api.pojo.vm.coupon.PCouponDetailVm;
import com.wxapp.market.api.pojo.vm.coupon.PCouponGoodsVm;
import com.wxapp.market.api.pojo.vm.coupon.PCouponListVm;
import com.wxapp.market.api.pojo.vm.coupon.PCouponPageVm;
import com.wxapp.market.api.pojo.vo.coupon.QCouponAddVo;
import com.wxapp.market.api.pojo.vo.coupon.QCouponPageVo;
import com.wxapp.market.api.pojo.vo.coupon.QCouponUpdateVo;
import com.wxapp.market.service.mapper.CouponGoodsMapper;
import com.wxapp.market.service.mapper.CouponMapper;
import com.wxapp.market.service.mapper.CouponUserMapper;
import com.wxapp.market.service.service.CouponService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;

import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lgl
 * @Description 优惠券管理
 * @Datetime 2022/7/4 16:14
 * @Modified By
 */
@Service
@RequiredArgsConstructor
public class CouponServiceImpl extends IBaseService implements CouponService {
    private final CouponMapper couponMapper;
    private final CouponGoodsMapper couponGoodsMapper;
    private final CouponUserMapper couponUserMapper;
    @Qualifier("com.wxapp.market.api.feign.GoodsFeign")
    private final GoodsFeign goodsFeign;

    @Override
    public ResultVm<String> add(QCouponAddVo qCouponAddVo, UserVo userVo) {
        var coupon = CopyUtil.copyObjectNew(qCouponAddVo, CouponDO::new, (s, r) -> {
            r.setCreateBy(userVo.getId());
            r.setWork(true);
            return null;
        });
        couponMapper.insert(coupon);
        return success("保存成功");
    }

    @Override
    public ResultVm<String> update(QCouponUpdateVo qCouponUpdateVo, UserVo userVo) {
        var coupon = couponMapper.selectById(qCouponUpdateVo.getId());
        if (coupon == null) {
            return error("没有查到优惠券信息");
        }
        CopyUtil.copyObject(qCouponUpdateVo, coupon, (s, r) -> {
            r.setUpdateBy(userVo.getId());
            return null;
        });
        couponMapper.updateById(coupon);
        return success("更新成功");
    }

    @Override
    public ResultVm<Page<PCouponPageVm>> getPage(QCouponPageVo qCouponPageVo) {
        Map<SFunction<CouponDO, ?>, SqlKeyword> condition = new HashMap<>();
        condition.put(CouponDO::getName, SqlKeyword.LIKE);
        var sCondition = ConditionUtil.getSCondition(CouponDO::new, qCouponPageVo, null, condition,null);
        var page = ConditionUtil.getPage(qCouponPageVo, CouponDO.class);
        var selectPage = couponMapper.selectPage(page, sCondition);
        var vmPage = CopyUtil.copyPage(selectPage, PCouponPageVm::new, null);
        return success(vmPage);
    }

    @Override
    public ResultVm<String> delete(String id) {
        var coupon = couponMapper.selectById(id);
        if (coupon == null) {
            return error("没有查到优惠券信息");
        }
        coupon.setStatus(false);
        couponMapper.updateById(coupon);
        return success("删除成功");
    }

    @Override
    public ResultVm<PCouponDetailVm> detail(String id) {
        var coupon = couponMapper.selectById(id);
        if (coupon == null) {
            return error("没有查到优惠券信息");
        }
        return success(CopyUtil.copyObjectNew(coupon, PCouponDetailVm::new, null));
    }

    @Override
    public ResultVm<String> addGoods(String id, List<String> productId) {
        var update = new LambdaUpdateWrapper<CouponGoodsDO>();
        update.eq(CouponGoodsDO::getCouponId, id)
                .eq(CouponGoodsDO::getStatus, true)
                .set(CouponGoodsDO::getStatus, false);
        couponGoodsMapper.update(null, update);
        List<CouponGoodsDO> goodsDOS = new ArrayList<>();
        productId.forEach(s -> goodsDOS.add(new CouponGoodsDO(s, id)));
        couponGoodsMapper.insertBatch(goodsDOS);
        return success("绑定商品成功");
    }

    @Override
    public ResultVm<List<PCouponGoodsVm>> getGoods(String id) {
        var query = new LambdaQueryWrapper<CouponGoodsDO>();
        query.eq(CouponGoodsDO::getCouponId, id)
                .eq(CouponGoodsDO::getStatus, true);
        var goods = couponGoodsMapper.selectList(query);
        if (CheckUtil.isNullList(goods)) {
            return success(new ArrayList<>());
        }
        var goodIds = goods.stream().map(CouponGoodsDO::getGoodsId).toList();
        var data = goodsFeign.list(goodIds).getData();
        var pGoodsVms = CopyUtil.copyListNew(data, PCouponGoodsVm::new, null);
        return success(pGoodsVms);
    }
    @Override
    public ResultVm<List<PCouponListVm>> getList(UserVo userVo, String productId) {
        var query = new LambdaQueryWrapper<CouponDO>();
        query.eq(CouponDO::getStatus, true);
        if (CheckUtil.isNotNullString(productId)) {
            var couponGoodsQuery = new LambdaQueryWrapper<CouponGoodsDO>();
            couponGoodsQuery.eq(CouponGoodsDO::getGoodsId, productId)
                    .eq(CouponGoodsDO::getStatus, true);
            var goods = couponGoodsMapper.selectList(couponGoodsQuery);
            if (CheckUtil.isNotNullList(goods)) {
                var couponId = goods.stream().map(CouponGoodsDO::getCouponId).toList();
                query.in(CouponDO::getId, couponId);
            }
        }
        if (userVo != null && CheckUtil.isNotNullString(userVo.getId())) {
            var couponUserQuery = new LambdaQueryWrapper<CouponUserDO>();
            couponUserQuery.eq(CouponUserDO::getUserId, userVo.getId())
                    .eq(CouponUserDO::getStatus, true);
            ;
            var users = couponUserMapper.selectList(couponUserQuery);
            if (CheckUtil.isNotNullList(users)) {
                var couponIds = users.stream().map(CouponUserDO::getCouponId).toList();
                query.in(CouponDO::getId, couponIds);
            }
        }
        var coupons = couponMapper.selectList(query);
        return success(CopyUtil.copyListNew(coupons, PCouponListVm::new, null));
    }

    @Override
    public ResultVm<String> receive(UserVo userVo, List<String> couponIds) {
        var couponUserQuery = new LambdaQueryWrapper<CouponUserDO>();
        couponUserQuery.eq(CouponUserDO::getUserId, userVo.getId())
                .in(CouponUserDO::getCouponId, couponIds)
                .eq(CouponUserDO::getStatus, true);
        var couponUserAll = couponUserMapper.selectList(couponUserQuery);
        if (CheckUtil.isNotNullList(couponUserAll) && couponUserAll.size() == couponIds.size()) {
            return error("优惠券已经领取了");
        }
        if (CheckUtil.isNotNullList(couponUserAll)) {
            var collect = couponUserAll.stream().map(CouponUserDO::getCouponId).toList();
            couponIds = couponIds.stream().filter(s -> !collect.contains(s)).toList();
        }
        var coupons = couponMapper.selectBatchIds(couponIds);
        if (CheckUtil.isNullList(coupons)) {
            return error("没有查到优惠券信息");
        }
        List<CouponUserDO> couponUsers = new ArrayList<>();
        coupons.forEach(s -> {
            LocalDateTime startDate = LocalDateTime.now();
            LocalDateTime endDate = null;
            switch (s.getTimeType()) {
                case FIXED_DAY -> endDate = LocalDateTimeUtil.addTime(startDate, s.getDays(), ChronoUnit.DAYS);
                case FIXED_TIME -> {
                    startDate = s.getStartTime();
                    endDate = s.getEndTime();
                }
            }
            couponUsers.add(new CouponUserDO(userVo.getId(), s.getId(), startDate, endDate));
        });
        couponUserMapper.insertBatch(couponUsers);
        return success("领取成功");
    }

    @Override
    public ResultVm<Integer> getCouponCount(String userId) {
        LambdaQueryWrapper<CouponUserDO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(CouponUserDO::getUserId, userId).eq(CouponUserDO::getStatus, true);
        var aLong = couponUserMapper.selectCount(wrapper);
        return success(aLong.intValue());
    }
}
